/*
 * Copyright 2002-2020 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.core.metrics;

import java.util.function.Supplier;

import org.springframework.lang.Nullable;

/**
 * 步骤记录{@link ApplicationStartup}期间发生的特定阶段或动作的指标。
 *
 * 一个{@code StartupStep}的生命周期如下。
 * 该步骤被创建，并通过调用{@link ApplicationStartup#start(String)}来启动。
 * 该步骤通过调用{@link ApplicationStartup#start(String) the application startup}创建并启动。
 * 并且被分配一个唯一的{@link StartupStep#getId() id}。
 * 然后我们可以在处理过程中用{@link Tags}附加信息。
 * 然后我们需要标记该步骤的{@link #end()}。
 *
 *
 * 实施可以跟踪步骤的 "执行时间 "或其他度量。
 *
 * @author Brian Clozel
 * @since 5.3
 */
public interface StartupStep {

	/**
	 * 返回启动步骤的名称。
	 * 一个步骤的名称描述了当前的行动或阶段。
	 * 这个技术名称应该是". "命名的，可以重复使用，以描述应用程序启动期间的其他类似步骤的实例。
	 * 在应用程序启动期间的类似步骤。
	 */
	String getName();

	/**
	 * 返回该步骤在应用程序启动时的唯一ID。
	 */
	long getId();

	/**
	 * 如果有的话，返回父步骤的ID。
	 * 父步骤是在创建当前步骤时最近启动的步骤。
	 * 当当前步骤被创建时。
	 */
	@Nullable
	Long getParentId();

	/**
	 * 在步骤中添加一个{@link Tag}。
	 * @param key 目标key
	 * @param value 目标value
	 */
	StartupStep tag(String key, String value);

	/**
	 * 	 * 在步骤中添加一个{@link Tag}。
	 * @param key 目标key
	 * @param value {@link Supplier} 为目标value
	 */
	StartupStep tag(String key, Supplier<String> value);

	/**
	 * 返回这个步骤的{@link Tag}集合。
	 */
	Tags getTags();

	/**
	 *  记录步骤的状态和可能的其他指标，如执行时间。
	 *  一旦结束，就不允许改变步骤的状态。
	 */
	void end();


	/**
	 * 不可变的{@link Tag}的集合。
	 */
	interface Tags extends Iterable<Tag> {
	}


	/**
	 * 简单的key/value关联，用于存储步骤元数据。
	 */
	interface Tag {

		/**
		 * 返回{@code Tag}的名称。
		 */
		String getKey();

		/**
		 * 返回{@code Tag}的value.
		 */
		String getValue();
	}

}
